﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Blizzard.Contracts;

namespace Blizzard.Container
{
   static class DBObjectContainer
    {

       private static Dictionary<Key, WrappedData> innerContainer = new Dictionary<Key, WrappedData>();

       internal static void ClearContainer()
       {
           innerContainer.Clear();
       }

        internal static void Add(IDataObject obj)
        {
            Key key = new Key(obj.Id, obj.GetType());
            WrappedData data = new WrappedData(obj);


            innerContainer.Add(key, data);
        }

        internal static bool HasTheObject(int Id, Type type)
        {

            Key key = new Key(Id, type);
            return innerContainer.ContainsKey(key);           

        }

        internal static List<WrappedData> GetAllWrappedData()
        {
            List<WrappedData> list = new List<WrappedData>();

            foreach (WrappedData data in innerContainer.Values)
            {
                list.Add(data);
            }

            return list;
        }

        internal static List<IDataObject> GetAllDataObjects()
        {
            List<IDataObject> list = new List<IDataObject>();

            foreach (WrappedData data in innerContainer.Values)
            {
                list.Add(data.innerDataObject);
            }

            return list;
        }

      
        internal static IDataObject GetDataObject(int Id, Type type)
        {
            Key key = new Key(Id,type);

             WrappedData data = null;

            if (innerContainer.ContainsKey(key))
                data =  innerContainer[key];

            if (data != null)
            {
                return data.innerDataObject;
            }
            else
            {
                return null;
            }

        }

        internal static void RemoveFromContainer(IDataObject obj)
        {

            Key key = new Key(obj.Id , obj.GetType());
            innerContainer.Remove(key);
            
        }


       //====================

        internal static bool PropertyAlreadyFilledFromDatabase(IDataObject obj, string property)
        {

            Key key = new Key(obj.Id, obj.GetType());

            if (innerContainer.ContainsKey(key))
            {

                WrappedData data = innerContainer[key];

                if (data.PropertyFilled.ContainsKey(property))
                {
                    return data.PropertyFilled[property];
                }
            }

            return false;
        }

        internal static void MarkPropertyAsFilledFromDatabase(IDataObject obj, string property)
        {

            Key key = new Key(obj.Id, obj.GetType());
       
            if (innerContainer.ContainsKey(key))
            {
                WrappedData data = innerContainer[key];
                
                if(!data.PropertyFilled.ContainsKey(property))
                data.PropertyFilled.Add(property, true);
            }
        }

        internal static void MarkAsChanged(IDataObject obj)
        {
            Key key = new Key(obj.Id, obj.GetType());
            WrappedData data = new WrappedData(obj);

            if (innerContainer.ContainsKey(key))
                innerContainer[key].IsChanged = true;

        }

        internal static void MarkForDeletion(IDataObject obj)
        {
            Key key = new Key(obj.Id, obj.GetType());
            WrappedData data = new WrappedData(obj);

            if (innerContainer.ContainsKey(key))
                innerContainer[key].IsMarkedForDeletion = true;

        }

        private struct Key
        {

            private int _id;
            private Type _dataObjectType;

            public Key(int Id , Type DataObjectType)
            {
                _id = Id;
                _dataObjectType = DataObjectType;
            }

            internal int Id { get { return _id; } }
            internal Type ObjectType { get { return _dataObjectType; } }
        }


    }

   internal class WrappedData
   {
       private Dictionary<string, bool> propertyFilled = new Dictionary<string, bool>();
       private IDataObject _innerObj;

       public WrappedData(IDataObject innerObj)
       {
           _innerObj = innerObj;
       }

       internal IDataObject innerDataObject { get { return _innerObj; } }
       internal bool IsChanged { get; set; }
       internal bool IsMarkedForDeletion { get; set; }
       internal Dictionary<string, bool> PropertyFilled
       {
           get { return propertyFilled; }
       }

   }
}
